/*******************************************************************************
 * Copyright (c) 2007 TOPCASED. All rights reserved. This program
 * and the accompanying materials are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Topcased contributors and others - initial API and implementation
 *******************************************************************************/
/**
 * This is a fork of the UML2Java Plug-in developed by Topcased and released under
 * the Eclipse EPL License. http://www.eclipse.org/legal/epl-v10.html
 * In accordance with the license, I have forked the UML2Java plugin and have adapted
 * it to suit the needs of a UML2QoS instrumentation code generator for PHP.
 * 
 * @author Alexandru Burdusel
 */
package org.topcased.uml2qos;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.topcased.uml2qos.log.Uml2QosLog;

import fr.obeo.acceleo.chain.ActionSet;
import fr.obeo.acceleo.chain.ChainFactory;
import fr.obeo.acceleo.chain.EmfMetamodel;
import fr.obeo.acceleo.chain.Folder;
import fr.obeo.acceleo.chain.Generate;
import fr.obeo.acceleo.chain.Generator;
import fr.obeo.acceleo.chain.Log;
import fr.obeo.acceleo.chain.Model;
import fr.obeo.acceleo.chain.Repository;
import fr.obeo.acceleo.chain.impl.spec.CChain;
import fr.obeo.acceleo.ecore.factories.EFactory;
import fr.obeo.acceleo.ecore.factories.FactoryException;
import fr.obeo.acceleo.tools.resources.Resources;

/**
 * Class that is used for initializing the Acceleo Generator (copy required files, create a chain, etc...).
 * @author Ariel RAMPHUL (Sopra Group - Toulouse)
 */
public class GenQos implements IObjectActionDelegate {

    /**
     * Selected chain file
     */
    public static IFile mFile;
    public static IFile currentModel;
    public static String output;
    public static String root;

    private ISelection selection;

    /**
     * Constructor for GenJava
     */
    public GenQos() {
        super();
    }

    /**
     * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
     */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
    }
    
    /**
     * @see IActionDelegate#run(IAction)
     */
    public void run(IAction action) {
        
        try{
            String metamodelURI = "http://www.eclipse.org/uml2/2.1.0/UML";
            IFile file = (IFile) ((StructuredSelection)selection).getFirstElement();
            currentModel = file;
            IPath modelPath = file.getFullPath();
            //References to files in the project
            String mtFile = "";
            IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
            root = myWorkspaceRoot.getLocation().toString();
            //Temporary project
            IProject tmpProject = myWorkspaceRoot.getProject(".uml2qos");

            //Create and open if necessary
            if (!tmpProject.exists()) {
                tmpProject.create(null);
            }
            if (!tmpProject.isOpen()) {
                tmpProject.open(null);
            }
            
            CChain chain = new CChain();

            //Repository
            Repository repository = ChainFactory.eINSTANCE.createRepository();
            EFactory.eSet(chain,"repository",repository);

            //Action Set
            ActionSet actionSet = ChainFactory.eINSTANCE.createActionSet();
            EFactory.eAdd(chain,"actions",actionSet);

            //Model file
            Model model = ChainFactory.eINSTANCE.createModel();
            EFactory.eAdd(repository,"files",model);
            EFactory.eSet(model,"path",modelPath.toString());

            //Retrieve output path 
            output = getModel().getPersistentProperty(new QualifiedName("", "OUTPUT_PATH"));   
            //Folder verification
            IPath chkPath;
            chkPath = modelPath.removeLastSegments(modelPath.segmentCount());
            if (output == null)
            {
                output = modelPath.removeLastSegments(1).toString();            
            }
            chkPath = chkPath.append(output);
            if (!myWorkspaceRoot.exists(chkPath))
            {
                output = modelPath.removeLastSegments(1).toString();
                Uml2QosLog.log(4, "Cannot access to output folder. Using default folder (" + output + ")");
            }         

            //Target folder
            Folder folder = ChainFactory.eINSTANCE.createFolder();
            EFactory.eAdd(repository,"files",folder);
            EFactory.eSet(folder,"path",output);
            
            //Log
            Log log = ChainFactory.eINSTANCE.createLog();
            EFactory.eAdd(repository,"files",log);
            EFactory.eSet(log,"path",output + modelPath.removeFileExtension().lastSegment() + ".log.txt");

            //Metamodel file
            EmfMetamodel pim = ChainFactory.eINSTANCE.createEmfMetamodel();
            EFactory.eAdd(repository,"files",pim);
            EFactory.eSet(pim,"path",metamodelURI);
            
            //Retrieve TMP file
            IPath tmpPath;
            tmpPath = modelPath.removeLastSegments(modelPath.segmentCount());
            tmpPath = tmpPath.append(output);
            tmpPath = tmpPath.append("tmp");
            mFile = myWorkspaceRoot.getFile(tmpPath);

            //Script files and generate actions
            Generator script = ChainFactory.eINSTANCE.createGenerator();
            EFactory.eAdd(repository,"files",script);
            mtFile = "org.topcased.uml2qos.generator/src/uml2qos.mt";
            EFactory.eSet(script,"path", mtFile);
            
            //Script files and generate actions
            Generator scriptAspect = ChainFactory.eINSTANCE.createGenerator();
            EFactory.eAdd(repository,"files",scriptAspect);
            mtFile = "org.topcased.uml2qos.generator/src/uml2qosaspect.mt";
            EFactory.eSet(scriptAspect,"path", mtFile);

            Generate gAction = ChainFactory.eINSTANCE.createGenerate();
            EFactory.eAdd(actionSet,"actions",gAction);

            EFactory.eSet(gAction,"documentation","org.topcased.uml2qos");     
            EFactory.eSet(gAction,"folder",folder);
            EFactory.eSet(gAction,"log",log);
            EFactory.eSet(gAction,"metamodel",pim);
            EFactory.eSet(gAction,"model",model);
            EFactory.eSet(gAction,"generator",script);
            
            
            Generate gActionAspect = ChainFactory.eINSTANCE.createGenerate();
            EFactory.eAdd(actionSet,"actions",gActionAspect);

            EFactory.eSet(gActionAspect,"documentation","org.topcased.uml2qos");     
            EFactory.eSet(gActionAspect,"folder",folder);
            EFactory.eSet(gActionAspect,"log",log);
            EFactory.eSet(gActionAspect,"metamodel",pim);
            EFactory.eSet(gActionAspect,"model",model);
            EFactory.eSet(gActionAspect,"generator",scriptAspect);
            

            //Register the default resource factory -- only needed for stand-alone!
            IFile fchain = tmpProject.getFile("uml2qos.chain");
            URI chainURI = Resources.createPlatformResourceURI(fchain.getFullPath().toString());
            ResourceSet resourceSet = new ResourceSetImpl();
            resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl());
            Resource chainResource = resourceSet.createResource(chainURI);
            chainResource.getContents().add(chain);
            chain.setFile(fchain);
            chainResource.save(Collections.EMPTY_MAP);
            
            GenQosOperation operation = new GenQosOperation(chain);
            PlatformUI.getWorkbench().getProgressService().run(false, false, operation);

        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        catch (CoreException e)
        {
            e.printStackTrace();
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (FactoryException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * @see IActionDelegate#selectionChanged(IAction, ISelection)
     */
    public void selectionChanged(IAction action, ISelection pSelection) {
        this.selection = pSelection;
    }
    
    /**
     * Get the tempory file
     * @return the tempory file
     */
    protected static IFile getmFile()
    {
        return mFile;
    }

    /**
     * Get the model file
     * @return the model file
     */
    public static IFile getModel()
    {
        return currentModel;
    }
    
    public static String getModelName()
    {
    	String s = currentModel.getLocation().lastSegment().toString();
        return s.substring(0,s.length()-4);
    }
    
    public static String getModelPath()
    {
        return root + currentModel.getFullPath();
    }    
    
    public static String getOutputPath()
    {
    	return root + output;
    }
    
}